home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / utilities / bmfc000.lha / BMFC / src / bmfc / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-31  |  5.8 KB  |  273 lines

  1. /**************************************/
  2. /* parse.c                            */
  3. /* for BMFC 0.00                      */
  4. /* Copyright 1992 by Adam M. Costello */
  5. /**************************************/
  6.  
  7.  
  8. #include <limits.h>
  9.  
  10. #if UCHAR_MAX != 255
  11. #error ---------------------------------------
  12. #error Danger!  Danger!  UCHAR_MAX is not 255!
  13. #error ---------------------------------------
  14. #endif
  15.  
  16. #include "parse.h"  /* Makes sure we're consistent with the */
  17.                     /* prototypes.  Also includes <stdio.h> */
  18. #include "error.h"
  19. #include <ctype.h>
  20.  
  21.  
  22. static FILE *f = NULL;
  23.  
  24. static unsigned long line, pos;
  25.  
  26. static unsigned char *word = NULL, *wordend = NULL, *wordlimit = NULL;
  27.  
  28. static int wordsize = 128, chr, prevchr, escaped;
  29.  
  30. static const char
  31.  
  32.   /* Error messages: */
  33.  
  34.   *const endwithescape = "Input file ends with an escape.\n",
  35.   *const endinsidecom  = "Input file ends inside a comment.\n",
  36.   *const endnobegin    = "end-comment with no matching begin-comment.\n";
  37.  
  38. static unsigned char digvaltable[UCHAR_MAX + 1];
  39.  
  40.  
  41. #define isEOF(c)       ((c) == EOF)
  42. #define isnewline(c)   ((c) == '\n')
  43. #define isescape(c)    ((c) == '\\')
  44. #define isbegincom(c)  ((c) == '{')
  45. #define isendcom(c)    ((c) == '}')
  46. #define isinstrsep(c)  ((c) == ';')
  47. #define isblank(c)     isspace(c)
  48.  
  49.  
  50. static void verynextchr(void)  /* Reads next character, taking */
  51. {                              /* care of line and pos.        */
  52.   int prevchr;
  53.  
  54.   prevchr = chr;
  55.   chr = fgetc(f);
  56.  
  57.   if (!isEOF(chr)) {
  58.     if (isnewline(prevchr)) {
  59.       ++line;
  60.       pos = 1;
  61.     } else ++pos;
  62.   }
  63. }
  64.  
  65.  
  66. static void skipcomment(void);
  67.  
  68.  
  69. static void nextchr(void)  /* Reads the next character, skipping comments,  */
  70. {                          /* taking care of escapes by setting the escaped */
  71.   verynextchr();           /* flag and reading another character.           */
  72.  
  73.   while (isbegincom(chr)) skipcomment();
  74.  
  75.   if (isescape(chr)) {
  76.     verynextchr();
  77.     escaped = 1;
  78.     if (isEOF(chr)) parsefailf(endwithescape);
  79.   } else escaped = 0;
  80. }
  81.  
  82.  
  83. static void skipcomment(void)  /* Reads up to the character following */
  84. {                              /* the next unmatched end-comment.     */
  85.   do {
  86.     nextchr();
  87.     if (isEOF(chr)) parsefailf(endinsidecom);
  88.   } while (escaped || !isendcom(chr));
  89.  
  90.   verynextchr();
  91. }
  92.                     
  93.  
  94. static void nextvisiblechr(void)
  95.   /* Calls nextchr() and checks for end-comment. After calling           */
  96.   /* nextvisiblechr(), chr cannot be an escape or begin- or end-comment. */
  97. {
  98.   nextchr();
  99.   if (isendcom(chr)) parsefailf(endnobegin);
  100. }
  101.  
  102.  
  103. void beginparsing(FILE *infile)
  104. {
  105.   /* The following table is necessary because we can't assume we're using */
  106.   /* the ASCII character set.  Theoretically, this source could have been */
  107.   /* translated to another character set in which the digits are not      */
  108.   /* adjacent, so a table is necessary to find their values.              */
  109.  
  110.   if (!digvaltable['1']) {
  111.     digvaltable['1'] =  1;
  112.     digvaltable['2'] =  2;
  113.     digvaltable['3'] =  3;
  114.     digvaltable['4'] =  4;
  115.     digvaltable['5'] =  5;
  116.     digvaltable['6'] =  6;
  117.     digvaltable['7'] =  7;
  118.     digvaltable['8'] =  8;
  119.     digvaltable['9'] =  9;
  120.     digvaltable['A'] = 10;
  121.     digvaltable['B'] = 11;
  122.     digvaltable['C'] = 12;
  123.     digvaltable['D'] = 13;
  124.     digvaltable['E'] = 14;
  125.     digvaltable['F'] = 15;
  126.     digvaltable['a'] = 10;
  127.     digvaltable['b'] = 11;
  128.     digvaltable['c'] = 12;
  129.     digvaltable['d'] = 13;
  130.     digvaltable['e'] = 14;
  131.     digvaltable['f'] = 15;
  132.   }
  133.  
  134.   f = infile;
  135.   line = 1;
  136.   pos = 0;
  137.   chr = EOF;
  138.   escaped = 0;
  139.   nextvisiblechr();
  140. }
  141.  
  142.  
  143. #define clearword()  { wordend = word; }
  144.  
  145.  
  146. static void appendword(int c)  /* Puts character c at the end of word. */
  147. {
  148.   if (wordend == wordlimit)
  149.   {
  150.     char *oldword = word, *oldwordend = wordend;
  151.  
  152.     wordsize *= 2;
  153.     word = (char *) malloc(wordsize * sizeof (char));
  154.     if (!word) failf(outofmem);
  155.     wordlimit = word + wordsize;
  156.     wordend = word;
  157.     while (oldword != oldwordend) *wordend++ = *oldword++;
  158.   }
  159.  
  160.   *wordend++ = c;
  161. }
  162.  
  163.  
  164. const unsigned char *nextword(void)
  165. {
  166.   clearword();
  167.  
  168.   /* Look for beginning of word: */
  169.  
  170.   while (!escaped) {
  171.     if (isinstrsep(chr) || isEOF(chr)) {
  172.       appendword(0);
  173.       return word;
  174.     }
  175.     if (!isblank(chr)) break;
  176.     nextvisiblechr();
  177.   }
  178.  
  179.   /* Beginning found.  Now look for end: */
  180.  
  181.   do {
  182.     appendword(chr);
  183.     nextvisiblechr();
  184.   } while (escaped || !isEOF(chr) && !isinstrsep(chr) && !isblank(chr));
  185.  
  186.   /* End found. */
  187.  
  188.   appendword(0);
  189.   return word;
  190. }
  191.  
  192.  
  193. int nextinstr(void)
  194. {
  195.   while (escaped || !isEOF(chr) && !isinstrsep(chr)) nextvisiblechr();
  196.   if (isEOF(chr)) return 0;
  197.   nextvisiblechr();
  198.   return 1;
  199. }
  200.  
  201.  
  202. #define maxint         4294967295
  203. #define isdollar(c)    ((c) == '$')
  204. #define ispercent(c)   ((c) == '%')
  205. #define isbit(c)       ((c) == '0' || (c) == '1')
  206. #define digval(c)      digvaltable[c]
  207.  
  208.  
  209. int wordtoul(const unsigned char *word, unsigned long *ulptr)
  210. {
  211.   unsigned long value = 0, dv;
  212.   int c;
  213.  
  214.   c = *word;
  215.  
  216.   if (isdigit(c)) {
  217.  
  218.     do {
  219.       if (value > maxint / 10) return 0;
  220.       value *= 10;
  221.       dv = digval(c);
  222.       if (value > maxint - dv) return 0;
  223.       value += dv;
  224.       c = *++word;
  225.     } while (isdigit(c));
  226.     if (c) return 0;
  227.  
  228.   } else if (isdollar(c)) {
  229.  
  230.     c = *++word;
  231.     if (!isxdigit(c)) return 0;
  232.     do {
  233.       if (value > maxint / 16) return 0;
  234.       value *= 16;
  235.       dv = digval(c);
  236.       if (value > maxint - dv) return 0;
  237.       value += dv;
  238.       c = *++word;
  239.     } while (isxdigit(c));
  240.     if (c) return 0;
  241.  
  242.   } else if (ispercent(c)) {
  243.  
  244.     c = *++word;
  245.     if (!isbit(c)) return 0;
  246.     do {
  247.       if (value > maxint / 2) return 0;
  248.       value *= 2;
  249.       dv = digval(c);
  250.       if (value > maxint - dv) return 0;
  251.       value += dv;
  252.       c = *++word;
  253.     } while (isbit(c));
  254.     if (c) return 0;
  255.  
  256.   } else return 0;
  257.  
  258.   *ulptr = value;
  259.   return 1;
  260. }
  261.  
  262.  
  263. unsigned long linenum(void)
  264. {
  265.   return line;
  266. }
  267.  
  268.  
  269. unsigned long position(void)
  270. {
  271.   return pos;
  272. }
  273.